# views.py
from rest_framework import filters
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authentication import TokenAuthentication
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import viewsets, permissions, pagination, status
from rest_framework.decorators import action
from .models import UserProfile
from rest_framework import generics
from django.utils import timezone
from rest_framework.views import APIView
import logging
logger = logging.getLogger(__name__)

import subprocess
import tempfile
from .models import (
    Student,
    ReadingMaterial,
    SingleChoiceQuestion,
    MultipleChoiceQuestion,
    FillInBlankQuestion,
    Task,
    Experiment,
    StudentExperimentProgress,
    StudentAnswerRecord,
    TeacherEvaluation,
    ExperimentAnnouncement,
    StudentGroup,
    CodeSubmission,
    CodeQuestion



)
from .serializers import (
    StudentSerializer,
    LoginSerializer,
    ReadingMaterialSerializer,
    SingleChoiceQuestionSerializer,
    MultipleChoiceQuestionSerializer,
    FillInBlankQuestionSerializer,
    TaskSerializer,
    ExperimentSerializer,
    StudentExperimentProgressSerializer,
    StudentAnswerRecordSerializer,
    StudentGroupSerializer,
    PublicReadingMaterialSerializer,
    PublicSingleChoiceQuestionSerializer,
    PublicMultipleChoiceQuestionSerializer,
    PublicFillInBlankQuestionSerializer,
    PublicTaskSerializer,
    PublicExperimentSerializer,
    TeacherEvaluationSerializer,
    ExperimentAnnouncementSerializer,
    CodeQuestionSerializer,
    CodeSubmissionSerializer
)

# 登录接口
class LoginView(APIView):
    authentication_classes = []
    serializer_class = LoginSerializer

    def post(self, request, *args, **kwargs):
        logger.debug(f"Login request data: {request.data}")
        print("Login request data:", request.data)
        serializer = self.serializer_class(data=request.data,
                                           context={'request': request})
        serializer.is_valid(raise_exception=True)
        
        validated_data_dict = serializer.validated_data 
        actual_user_object = validated_data_dict['user'] # Get the User instance

        token, created = Token.objects.get_or_create(user=actual_user_object)
        
        try:
            profile = actual_user_object.userprofile
            role = profile.role
        except UserProfile.DoesNotExist:
            UserProfile.objects.get_or_create(user=actual_user_object)
            profile = actual_user_object.userprofile
            role = profile.role

        requested_role = request.data.get('role')
        if requested_role and requested_role != role:
            return Response(
                {'detail': f'请从{ "教师" if role == "teacher" else "学生" }入口登录！'},
                status=status.HTTP_400_BAD_REQUEST
            )

        return Response({
            'token': token.key,
            'username': actual_user_object.username,
            'role': role, 
            'user_id': actual_user_object.id
        })

# 分页类不变
class StudentPagination(pagination.PageNumberPagination):
    page_size = 5
    page_size_query_param = 'page_size'
    max_page_size = 100

# 自定义权限：必须是 Student 类型用户才能访问
class IsStudent(permissions.BasePermission):
    def has_permission(self, request, view):
        try:
            return request.user.userprofile.role == 'student'
        except UserProfile.DoesNotExist:
            return False

# 学生信息视图集
class StudentViewSet(viewsets.ModelViewSet):
    queryset = Student.objects.all().order_by('id')
    serializer_class = StudentSerializer
    pagination_class = StudentPagination
    permission_classes = [permissions.IsAuthenticated]

class StudentGroupViewSet(viewsets.ModelViewSet):
    queryset = StudentGroup.objects.all()
    serializer_class = StudentGroupSerializer
    permission_classes = [permissions.IsAuthenticated]

class PublicStudentListView(generics.ListAPIView):
    queryset = Student.objects.all().order_by('id')
    serializer_class = StudentSerializer
    pagination_class = StudentPagination
    permission_classes = [permissions.AllowAny]

# 阅读材料视图集
class ReadingMaterialViewSet(viewsets.ModelViewSet):
    queryset = ReadingMaterial.objects.all()
    serializer_class = ReadingMaterialSerializer
    permission_classes = [permissions.AllowAny]

# 单选题视图集
class SingleChoiceQuestionViewSet(viewsets.ModelViewSet):
    queryset = SingleChoiceQuestion.objects.all()
    serializer_class = SingleChoiceQuestionSerializer
    permission_classes = [permissions.AllowAny]

# 多选题视图集
class MultipleChoiceQuestionViewSet(viewsets.ModelViewSet):
    queryset = MultipleChoiceQuestion.objects.all()
    serializer_class = MultipleChoiceQuestionSerializer
    permission_classes = [permissions.AllowAny]

# 填空题视图集
class FillInBlankQuestionViewSet(viewsets.ModelViewSet):
    queryset = FillInBlankQuestion.objects.all()
    serializer_class = FillInBlankQuestionSerializer
    permission_classes = [permissions.AllowAny]

# 任务视图集
class TaskViewSet(viewsets.ModelViewSet):
    queryset = Task.objects.all()
    serializer_class = TaskSerializer
    permission_classes = [permissions.AllowAny]

# 实验视图集
class ExperimentViewSet(viewsets.ModelViewSet):
    queryset = Experiment.objects.all()
    serializer_class = ExperimentSerializer
    permission_classes = [permissions.AllowAny]

# 学生实验进度视图集
class StudentExperimentProgressViewSet(viewsets.ModelViewSet):
    queryset = StudentExperimentProgress.objects.all()
    serializer_class = StudentExperimentProgressSerializer
    permission_classes = [permissions.AllowAny]
    filter_backends = [filters.SearchFilter, filters.OrderingFilter]
    search_fields = ['experiment__id']
    @action(detail=True, methods=['post'])
    def complete_task(self, request, pk=None):
        progress = self.get_object()
        task_id = request.data.get('task_id')
        if not task_id:
            return Response({'error': '缺少任务ID'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            task = Task.objects.get(id=task_id)
            progress.completed_tasks.add(task)
            if progress.tasks.count() == progress.completed_tasks.count():
                progress.is_completed = True
                progress.submitted_at = timezone.now()
            progress.save()
            return Response({'status': '任务完成'})
        except Task.DoesNotExist:
            return Response({'error': '任务不存在'}, status=status.HTTP_404_NOT_FOUND)
    def get_queryset(self):
        queryset = super().get_queryset()
        experiment_id = self.request.query_params.get('experiment')
        user = self.request.user
        # 判断用户角色
        try:
            role = user.userprofile.role
        except Exception:
            role = None

        if role == 'student':
        # 只返回当前学生的实验进度
            student = getattr(user, 'student', None)
            if student:
                queryset = queryset.filter(student=student)
            else:
                queryset = queryset.none()
    # 老师或管理员默认返回所有
        if experiment_id:
            queryset = queryset.filter(experiment_id=experiment_id)
        return queryset

# 学生答题记录视图集
class StudentAnswerRecordViewSet(viewsets.ModelViewSet):
    queryset = StudentAnswerRecord.objects.all()
    serializer_class = StudentAnswerRecordSerializer
    authentication_classes = [TokenAuthentication]
    permission_classes = [permissions.IsAuthenticated]

    @action(detail=False, methods=['post'], url_path='get-or-create-for-task')
    def get_or_create_for_task(self, request):
        experiment_id = request.data.get('experiment_id')
        task_id = request.data.get('task_id')
        user = request.user

        if not experiment_id or not task_id:
            return Response(
                {"error": "Experiment ID and Task ID are required."},
                status=status.HTTP_400_BAD_REQUEST
            )

        try:
            experiment = Experiment.objects.get(pk=experiment_id)
            task = Task.objects.get(pk=task_id)
        except Experiment.DoesNotExist:
            return Response({"error": "Experiment not found."}, status=status.HTTP_404_NOT_FOUND)
        except Task.DoesNotExist:
            return Response({"error": "Task not found."}, status=status.HTTP_404_NOT_FOUND)

        record, created = StudentAnswerRecord.objects.get_or_create(
            student=user,
            experiment=experiment,
            task=task,
            defaults={ # These values are used only if a new record is created
                'single_choice_answers': {},
                'multiple_choice_answers': {},
                'fill_in_blank_answers': {}
            }
        )
        
        serializer = self.get_serializer(record)
        response_status = status.HTTP_201_CREATED if created else status.HTTP_200_OK
        return Response(serializer.data, status=response_status)

    @action(detail=True, methods=['post'])
    def submit_answers(self, request, pk=None):
        print(f"User trying to submit: {request.user}")
        print(f"Is authenticated: {request.user.is_authenticated}")
        # No need to check auth type here, permission_classes will handle it
        
        record = self.get_object() # This pk is the StudentAnswerRecord's pk

        # Ensure the user submitting is the owner of the record
        if record.student != request.user:
            return Response(
                {"detail": "You do not have permission to submit answers for this record."},
                status=status.HTTP_403_FORBIDDEN
            )

        answers_data = request.data.get('answers', {}) # From your TaskComponent's payload structure
        
       
        record.completed_at = timezone.now()
        record.single_choice_answers = answers_data.get('single_choice', record.single_choice_answers)
        record.multiple_choice_answers = answers_data.get('multiple_choice', record.multiple_choice_answers)
        record.fill_in_blank_answers = answers_data.get('fill_in_blank', record.fill_in_blank_answers)
        record.save()

        score = self.evaluate_answers(record) # evaluate_answers should use record.task
        progress, created = StudentExperimentProgress.objects.get_or_create(
            student=request.user,
            experiment=record.experiment  # 注意：record.experiment
        )
        progress.is_completed = True
        progress.score = score['total_score']
        progress.max_score = score['max_score']
        progress.submitted_at = timezone.now()
        progress.save()
        return Response({
        'status': '提交成功', 
        'score': score, 
        'record_id': record.id,
        'single_choice_answers': record.single_choice_answers,
        'multiple_choice_answers': record.multiple_choice_answers,
        'fill_in_blank_answers': record.fill_in_blank_answers
    })
    def get_queryset(self):
        # 只返回当前登录用户的答题记录
        return StudentAnswerRecord.objects.filter(student=self.request.user)
    def evaluate_answers(self, record):
    
        total_score = 0
        max_score = 0
        task_instance = record.task # Get the task associated with this record

        # 单选题评分
        for q_id_str, answer in record.single_choice_answers.items():
            q_id = int(q_id_str)
            try:
                question = task_instance.single_choice_questions.get(id=q_id)
                if answer == question.correct_answer:
                    total_score += 1
                max_score += 1
            except SingleChoiceQuestion.DoesNotExist:
                print(f"Warning: SingleChoiceQuestion with id {q_id} not found in task {task_instance.id}")
                pass

        # 多选题评分
        for q_id_str, answers in record.multiple_choice_answers.items():
            q_id = int(q_id_str)
            try:
                question = task_instance.multiple_choice_questions.get(id=q_id)
                correct_ans_set = set(list(question.correct_answers))
                user_ans_set = set(answers)
                if user_ans_set == correct_ans_set:
                    total_score += 1
                max_score += 1
            except MultipleChoiceQuestion.DoesNotExist:
                print(f"Warning: MultipleChoiceQuestion with id {q_id} not found in task {task_instance.id}")
                pass
        
        # 填空题评分
        for q_id_str, answer in record.fill_in_blank_answers.items():
            q_id = int(q_id_str)
            try:
                question = task_instance.fill_in_blank_questions.get(id=q_id)
                if answer.strip().lower() == question.correct_answer.strip().lower():
                    total_score += 1
                elif question.fuzzy_answers:
                    fuzzy_answers = [ans.strip().lower() for ans in question.fuzzy_answers.split(',')]
                    if answer.strip().lower() in fuzzy_answers:
                        total_score += 1
                max_score += 1
            except FillInBlankQuestion.DoesNotExist:
                print(f"Warning: FillInBlankQuestion with id {q_id} not found in task {task_instance.id}")
                pass
                
        return {'total_score': total_score, 'max_score': max_score}

# 公共阅读材料视图
class PublicReadingMaterialViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = ReadingMaterial.objects.all()
    serializer_class = PublicReadingMaterialSerializer
    permission_classes = [permissions.AllowAny]

# 公共单选题视图
class PublicSingleChoiceQuestionViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = SingleChoiceQuestion.objects.all()
    serializer_class = PublicSingleChoiceQuestionSerializer
    permission_classes = [permissions.AllowAny]

# 公共多选题视图
class PublicMultipleChoiceQuestionViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = MultipleChoiceQuestion.objects.all()
    serializer_class = PublicMultipleChoiceQuestionSerializer
    permission_classes = [permissions.AllowAny]

# 公共填空题视图
class PublicFillInBlankQuestionViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = FillInBlankQuestion.objects.all()
    serializer_class = PublicFillInBlankQuestionSerializer
    permission_classes = [permissions.AllowAny]

# 公共任务视图
class PublicTaskViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Task.objects.all()
    serializer_class = PublicTaskSerializer
    permission_classes = [permissions.AllowAny]

# 公共实验视图
class PublicExperimentViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Experiment.objects.all()
    serializer_class = PublicExperimentSerializer
    permission_classes = [permissions.AllowAny]

# 新增教师权限类
class IsTeacher(permissions.BasePermission):
    def has_permission(self, request, view):
        print("IsTeacher check: user =", request.user)
        print("Is authenticated:", request.user.is_authenticated)
        try:
            print("UserProfile role:", getattr(request.user.userprofile, "role", None))
            return getattr(request.user.userprofile, "role", None) == UserProfile.ROLE_TEACHER
        except Exception as e:
            print("IsTeacher Exception:", e)
            return False

# 新增教师实验管理视图
class TeacherExperimentViewSet(viewsets.ModelViewSet):
    queryset = Experiment.objects.all()
    serializer_class = ExperimentSerializer
    permission_classes = [permissions.IsAuthenticated, IsTeacher]

    def get_queryset(self):
        # 只返回当前教师创建的实验
        return self.queryset.filter(created_by=self.request.user)

    def perform_create(self, serializer):
        # 创建实验时自动设置创建者
        serializer.save(created_by=self.request.user)

    @action(detail=True, methods=['post'])
    def publish(self, request, pk=None):
        experiment = self.get_object()
        experiment.is_published = True
        experiment.save()
        return Response({'status': '实验已发布'})

    @action(detail=True, methods=['post'])
    def unpublish(self, request, pk=None):
        experiment = self.get_object()
        experiment.is_published = False
        experiment.save()
        return Response({'status': '实验已取消发布'})

    @action(detail=True, methods=['get'])
    def statistics(self, request, pk=None):
        experiment = self.get_object()
        # 统计所有分组下的学生数
        total_students = experiment.assigned_groups.aggregate(
            total=models.Count('students')
        )['total'] or 0
        # 已提交实验的学生数
        submitted_students = StudentExperimentProgress.objects.filter(
            experiment=experiment,
            is_completed=True
        ).count()
        # TODO: 计算平均分
        average_score = 0
        completion_rate = (submitted_students / total_students * 100) if total_students else 0

        data = {
            'experiment_id': experiment.id,
            'experiment_name': experiment.name,
            'total_students': total_students,
            'submitted_students': submitted_students,
            'average_score': average_score,
            'completion_rate': completion_rate
        }
        serializer = ExperimentStatisticsSerializer(data=data)
        serializer.is_valid(raise_exception=True)
        return Response(serializer.data)

# 新增教师评分视图
class TeacherEvaluationViewSet(viewsets.ModelViewSet):
    queryset = TeacherEvaluation.objects.all()
    serializer_class = TeacherEvaluationSerializer
    permission_classes = [permissions.IsAuthenticated, IsTeacher]
    
    def perform_create(self, serializer):
        serializer.save(teacher=self.request.user)

# 新增实验公告视图
class ExperimentAnnouncementViewSet(viewsets.ModelViewSet):
    queryset = ExperimentAnnouncement.objects.all()
    serializer_class = ExperimentAnnouncementSerializer
    permission_classes = [permissions.IsAuthenticated, IsTeacher]
    
    def perform_create(self, serializer):
        serializer.save(created_by=self.request.user)
    
    def get_queryset(self):
        experiment_id = self.request.query_params.get('experiment_id')
        if experiment_id:
            return self.queryset.filter(experiment_id=experiment_id)
        return self.queryset.all()
    
class PublicAnnouncementListView(generics.ListAPIView):
    queryset = ExperimentAnnouncement.objects.all().order_by('-is_pinned', '-created_at')
    serializer_class = ExperimentAnnouncementSerializer
    permission_classes = [permissions.AllowAny]

# 新增代码题视图
class CodeQuestionViewSet(viewsets.ModelViewSet):
    queryset = CodeQuestion.objects.all()
    serializer_class = CodeQuestionSerializer
    permission_classes = [permissions.AllowAny]

# 新增代码提交视图
class CodeSubmissionViewSet(viewsets.ModelViewSet):
    queryset = CodeSubmission.objects.all()
    serializer_class = CodeSubmissionSerializer
    permission_classes = [permissions.IsAuthenticated]

    def perform_create(self, serializer):
        # 保存代码提交时的用户信息
        submission = serializer.save(student=self.request.user)
        #评测代码
        question = submission.question
        code = submission.code
        input_data = question.input_format
        expected_output = question.output_format.strip()
        with tempfile.NamedTemporaryFile(mode='w+', suffix='.py', delete=False) as f:
            f.write(code)
            f.flush()
            try:
                result = subprocess.run(
                    ['python', f.name],
                    input=input_data.encode(),
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    timeout=5
                )
                output = result.stdout.decode().strip()
                if output == expected_output:
                    submission.result = 'Accepted'
                    submission.score = 1
                else:
                    submission.result = 'Wrong Answer'
                    submission.score = 0
                submission.feedback = result.stderr.decode()
            except subprocess.TimeoutExpired:
                submission.result = 'Time Limit Exceeded'
                submission.score = 0
                submission.feedback = '运行超时'
            submission.save()

   